package com.rom.stack;

/**
 *
 * 栈实现计算器。（中缀表达式）
 */
public class Calcuator {
    public static void main(String[] args) {

        String expression = "53+2*2-2";

        ArrayStack2 numStack = new ArrayStack2(10);
        ArrayStack2 operStack = new ArrayStack2(10);

        int index = 0;// 用于扫描表达式
        int num1 = 0;
        int num2 = 0;
        int oper = 0;
        int res = 0;
        char ch = ' ';  //每次扫描得到的char 保存到ch中

        String keepNum = "";
        //以此扫描字符
        while (true){
            //
            ch = expression.substring(index,index+1).charAt(0);
            if( operStack.isOper(ch) ){
                //是运算符
                if(!operStack.isEmpty()){
                    //判断优先级
                    if(operStack.priority(ch) <= operStack.priority(operStack.peek())){
                        //如果优先级高就要拿出来计算
                        num1 = numStack.popitem();
                        num2 = numStack.popitem();
                        oper = operStack.popitem();
                        res = numStack.cal(num1, num2, oper);
                        //计算结果入栈
                        numStack.additem(res);
                        //当前符号入栈
                        operStack.additem(ch);
                    }else{
                        operStack.additem(ch);
                    }
                }else{
                    //为空直接入栈
                    operStack.additem(ch);
                }
            }else{
//              numStack.additem(ch - '0');
                keepNum += ch;

                if(index  ==  expression.length() - 1){
                    numStack.additem(Integer.parseInt(keepNum));
                }else{
                    if( operStack.isOper(expression.substring(index+1,index+2).charAt(0))){
                        numStack.additem(Integer.parseInt(keepNum));
                        keepNum = "";
                    }
                }
            }
            if( ++index >= expression.length()){
                break;
            }
        }
        while (!operStack.isEmpty()){
            //如果优先级高就要拿出来计算
            num1 = numStack.popitem();
            num2 = numStack.popitem();
            oper = operStack.popitem();
            res = numStack.cal(num1, num2, oper);
            //计算结果入栈
            numStack.additem(res);
        }
        System.out.println("No."+ numStack.popitem());
    }
}

class ArrayStack2{

    private int maxSize;
    private int[] stack;
    private int top = -1;

    public ArrayStack2(int maxSize) {
        this.maxSize = maxSize;
        this.stack = new int[this.maxSize];
    }

    public boolean isFUll(){
        return top == maxSize-1;
    }
    public boolean isEmpty(){
        return top == -1;
    }
    //入栈
    public void additem(int num){
        if(isFUll()){
            System.out.println("栈满");
            return;
        }
        stack[++top] = num;
    }

    //出栈
    public int popitem() {

        if(top == -1){
//            System.out.println("栈空");
            throw new RuntimeException("栈空");
        }
        int value = stack[top--];
        return value;
    }
    //遍历
    public void list(){
        if(isEmpty()){
            System.out.println("栈空");
            return;
        }
        for (int i = top; i >= 0; i--) {
            System.out.println("NO."+stack[i]);
        }
    }
    //是不是算术符
    public boolean isOper(char ch){
        return ch=='+'||ch=='-'||ch=='*'||ch=='/';
    }
    //
    public int peek(){
        return stack[top];
    }
    //返回算术符号优先级
    public int priority(int oper){
        if(oper == '*'||oper == '/'){
            return 1;
        }else if(oper == '+'||oper == '-'){
            return 0;
        }else{
            return -1;
        }
    }
    //
    public int cal(int num1,int num2,int oper){

        int res = 0;
        switch (oper){
            case '+':
                res = num1+num2;
                break;
            case '-':
                res = num2-num1;
                break;
            case '*':
                res = num1*num2;
                break;
            case '/':
                res = num2 / num1;
                break;
        }
        return res;
    }
}